package com.example.robertluozizhao.framecollectdemo.view.opengl;

/**
 * Created by Lzz on 3/30/2020.
 */

import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

/**
 * 定义一个三角形 OG001-001
 */
public class Triangle {

    /**
     * OpenGL ES对象，包含了用来绘制一个或者多个形状的shader
     */
    private final int mProgram;

    private FloatBuffer vertexBuffer;

    // 数组中每个顶点的坐标数
    static final int COORDS_PER_VERTEX = 3;

    static float triangleCoords[] = {   // 按照逆时针方向:
            0.0f,  0.5f, 0.0f, // top
            -0.5f, -0.455f, 0.0f, // bottom left
            0.5f, -0.555f, 0.0f  // bottom right
    };

    // 设置颜色RGBA（red green blue alpha）
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };


    private int mPositionHandle;
    private int mColorHandle;
    private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex


    public Triangle() {
        // 为存放形状的坐标，初始化顶点字节缓冲
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (坐标数 * 4 )float 占四个字节
                triangleCoords.length * 4);
        // 使用设备的本点字节序
        bb.order(ByteOrder.nativeOrder());

        // 从ByteBuffer创建一个浮点缓冲
        vertexBuffer = bb.asFloatBuffer();
        // 把坐标加入FloatBuffer中
        vertexBuffer.put(triangleCoords);
        // 设置buffer，从第一个坐标开始读
        vertexBuffer.position(0);


        /******** OG001-003-003  编译shader代码，将着色器添加到OpengGL ES program对象中，然后链接到program *********/
        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
                vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
                fragmentShaderCode);

        // 创建一个空的 OpenGL ES Program
        mProgram = GLES20.glCreateProgram();

        // 将vertex shader 添加到 program
        GLES20.glAttachShader(mProgram, vertexShader);

        // 将fragment shader 添加到 program
        GLES20.glAttachShader(mProgram, fragmentShader);

        // 创建一个可执行的 OpenGL ES program
        GLES20.glLinkProgram(mProgram);
    }




    /********************** 绘制图形  OG001-003*******************************/
    /**
     * 准备工作：
     * vertex Shader - 顶点着色器，用来绘制图形的形状
     * Fragment Shader - 片段着色器，用来绘制图形的颜色或者是纹理
     * Program - 一个OpenGL ES对象，包含了用来绘制一个或者多个形状的shader。
     * 你需要定义至少一个顶点着色器和片段着色器，这些形状必须被编译然后被添加到一个OpenGL ES program中，program之后会被用来绘制形状。
     */

    /*OG001-003-001 下面代码是绘制三角形时定义的着色器语言：*/
//    private final String vertexShaderCode =
//            "attribute vec4 vPosition;" +
//                    "void main() {" +
//                    "  gl_Position = vPosition;" +
//                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";


    /**
     * OG001-003-004 设置了顶点着色器和片段着色器的位置和颜色
     */
    public void draw() {
        // 将program 添加到 OpenGL ES 环境中
        GLES20.glUseProgram(mProgram);

        // 获取指向vertex shader的成员vPosition的句柄
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

        // 启用一个指向三角形的顶点数组的句柄
        GLES20.glEnableVertexAttribArray(mPositionHandle);

        // 准备三角形的坐标数据
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);

        // 获取指向fragment shader的成员vColor的句柄
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

        // 设置三角形的颜色
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);

        // 画三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

        // 禁用指向三角形的定点数组
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }


    /*****************OG001-004-003 使用投影和相机转换****************/
    private final String vertexShaderCode =
            //这个矩阵成员变量提供了一个勾子来操控
            // 使用这个顶点着色器的对象的坐标
            "uniform mat4 uMVPMatrix;" +
                    "attribute vec4 vPosition;" +
                    "void main() {" +
                    // the matrix must be included as a modifier of gl_Position
                    // Note that the uMVPMatrix factor *must be first* in order
                    // for the matrix multiplication product to be correct.
                    "  gl_Position = uMVPMatrix * vPosition;" +
                    "}";

    // Use to access and set the view transformation
    private int mMVPMatrixHandle;

    public void draw(float[] mvpMatrix) { // 传递计算出来的变换矩阵
        // 获得形状的变换矩阵的句柄
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

        // Pass the projection and view transformation to the shader
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

        // 绘制三角形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }
}
